/*
    Geocache: some utilities for managing and visualizing geocache information
    Copyright (C) 2008  Gary Jackson

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Triangle.java
 */

package com.thegbomb.sphere;

/**
 *
 * @author Gary Jackson
 */
public class Triangle {
    private Point A, B, C;
    private double a, b, c;
    private double alpha, beta, gamma;
    private double area;
    
    /**
     * Creates A new instance of Triangle
     */
    public Triangle(Point A, Point B, Point C) {
        if (A.equals(B) || A.equals(C) || B.equals(C))
            throw new SphereException("points are identical");
        
        if (A.isAntipodal(B) || A.isAntipodal(C) || B.isAntipodal(C))
            throw new SphereException("points are antipodal");
        
        Plane x = new Plane(A, B);
        Plane y = new Plane(A, C);

        if (new Plane(A, B).equals(new Plane(A, C)))
            throw new SphereException("points are colinear");
        
        this.A = A;
        this.B = B;
        this.C = C;
        
        this.a = B.distance(C);
        this.b = A.distance(C);
        this.c = A.distance(B);
        
        this.alpha = Math.acos((Math.cos(a) - Math.cos(b)*Math.cos(c))/(Math.sin(b)*Math.sin(c)));
        this.beta  = Math.acos((Math.cos(b) - Math.cos(c)*Math.cos(a))/(Math.sin(c)*Math.sin(a)));
        this.gamma = Math.acos((Math.cos(c) - Math.cos(a)*Math.cos(b))/(Math.sin(a)*Math.sin(b)));
        
        this.area = alpha + beta + gamma - Math.PI;
    }
    
    public Point centroid() {
        return new Point(A.getCartesian().add(B.getCartesian()).add(C.getCartesian()).sdiv(3.0d).normalize());
    }
    
    public double area() {
        return this.area; 
    }
    
    public Point getPointA() { return A; }
    public Point getPointB() { return B; }
    public Point getPointC() { return C; }
    
    public double getAngleA() { return a; }
    public double getAngleB() { return b; }
    public double getAngleC() { return c; }
    
    public double getAlpha() { return alpha; }
    public double getBeta() { return beta; }
    public double getGamma() { return gamma; }
    
    public Triangle rotate(Point axis, double angle) {
        return new Triangle(A.rotate(axis, angle), B.rotate(axis, angle), C.rotate(axis, angle));
    }
    
    public String toString() { return "[A: " + A + ", B: " + B + ", C: " + C + "]"; } 
}
